package buffbuildergui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import java.awt.geom.AffineTransform;

import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class BevelArrow extends JPanel
{
    jfMainFrame mainframe;
    public BevelArrow(jfMainFrame host) {
        super();
        mainframe = host;
    }

    public void paintComponent ( Graphics g ) {
        g.clearRect(0, 0, this.getWidth(),this.getHeight());
        ArrayList<EntityPanel> completed = new ArrayList<>();
        
        g.drawRect(0,0,5,5);
        for(int i = 0; i < mainframe.abilityList.size(); i++)
            descend(mainframe.abilityList.get(i).ownerPanel,completed,g);
        for(int i = 0; i < mainframe.buffList.size(); i++)
            descend(mainframe.buffList.get(i).ownerPanel,completed,g);
        g.setColor(Color.black);
    }
    
    Color getColor(EntityPanel ep) {
        float r=0,g=0,b=0,a=0.5f;
        Color former = ep.getBackground();
        r = former.getRed()/255;
        g = former.getGreen()/255;
        b = former.getBlue()/255;
        
        return new Color(r,g,b,a);
    }
    
    void descend(EntityPanel ep,ArrayList<EntityPanel> completed,Graphics g) {
        // prevent re-drawing
        if(completed.contains(ep))
            return;
        else
            completed.add(ep);
        
        // draw connectors
        int width = ep.getWidth();
        int startX = ep.getInPort().x;
        int startY = ep.getInPort().y;
        int endX = ep.getOutPort().x;
        int endY = ep.getOutPort().y;
        Graphics2D g2d = (Graphics2D)g;
        g2d.drawLine(startX,startY,endX,endY);
        
        // if this is an unowned buff, draw from the null box
        if(ep.parents.size() == 0) {
            Shape s = createArrowShape(new Point(3,3),ep.getInPort());
            g2d.setColor(getColor(ep));
            g2d.fill(s);
        }
        
        for(int i = 0; i < ep.children.size(); i++) {
            EntityPanel child = ep.children.get(i);
            Point start = new Point(endX,endY);
            
            Point stop = child.getInPort();
            Shape s = createArrowShape(start,stop);
            g2d.setColor(getColor(child));
            g2d.fill(s);
            descend(child,completed,g);
        }
    }

    public static Shape createArrowShape(Point fromPt, Point toPt) {
        Polygon arrowPolygon = new Polygon();
        AffineTransform transform = new AffineTransform();

        // calculate direction
        boolean tipsHoriz = false;
        if(Math.abs(fromPt.x - toPt.x) >= Math.abs(fromPt.y - toPt.y) && fromPt.x < toPt.x)
            tipsHoriz = true;
        
        int flipX = 1;
        int flipY = 1;
        
        if(fromPt.x > toPt.x)
            flipX = -1;
        if(fromPt.y - toPt.y > 0)
            flipY = -1;

        int midX = ((int)(fromPt.x + toPt.x)/2);
        int midY = ((int)(fromPt.y + toPt.y)/2);
        
        if(tipsHoriz)
        {
            if(fromPt.y != toPt.y)
            {
                arrowPolygon.addPoint(fromPt.x,fromPt.y-1);
                
                arrowPolygon.addPoint(midX+flipX*flipY*(1),fromPt.y-1);
                arrowPolygon.addPoint(midX+flipX*flipY*(1),toPt.y-1);
                
                arrowPolygon.addPoint(toPt.x-flipX*(5),toPt.y-1);
                arrowPolygon.addPoint(toPt.x-flipX*(5),toPt.y-4);
                arrowPolygon.addPoint(toPt.x,toPt.y);
                arrowPolygon.addPoint(toPt.x-flipX*(5),toPt.y+4);
                arrowPolygon.addPoint(toPt.x-flipX*(5),toPt.y+1);
                
                arrowPolygon.addPoint(midX-flipX*flipY*(1),toPt.y+1);
                arrowPolygon.addPoint(midX-flipX*flipY*(1),fromPt.y+1);
                
                arrowPolygon.addPoint(fromPt.x,fromPt.y+1);
            }
            else {
                arrowPolygon.addPoint(fromPt.x,fromPt.y-1);
                arrowPolygon.addPoint(toPt.x-5*flipX,toPt.y-1);
                arrowPolygon.addPoint(toPt.x-5*flipX,toPt.y-4);
                arrowPolygon.addPoint(toPt.x,toPt.y);
                arrowPolygon.addPoint(toPt.x-5*flipX,toPt.y+4);
                arrowPolygon.addPoint(toPt.x-5*flipX,toPt.y+1);                    
                arrowPolygon.addPoint(fromPt.x,fromPt.y+1);
            }
        }
        else {
            if(fromPt.x != toPt.x)
            {
                arrowPolygon.addPoint(fromPt.x+1,fromPt.y);
                
                arrowPolygon.addPoint(fromPt.x+1,midY-flipY*flipX*1);
                arrowPolygon.addPoint(toPt.x+1,midY-flipY*flipX*1);
                
                arrowPolygon.addPoint(toPt.x+1,toPt.y-flipY*5);
                arrowPolygon.addPoint(toPt.x+4,toPt.y-flipY*5);
                arrowPolygon.addPoint(toPt.x,toPt.y);
                arrowPolygon.addPoint(toPt.x-4,toPt.y-flipY*5);
                arrowPolygon.addPoint(toPt.x-1,toPt.y-flipY*5);
                
                arrowPolygon.addPoint(toPt.x-1,midY+flipX*flipY*1);
                arrowPolygon.addPoint(fromPt.x-1,midY+flipX*flipY*1);
                
                arrowPolygon.addPoint(fromPt.x-1,fromPt.y);
            }
            else {
                arrowPolygon.addPoint(fromPt.x+1,fromPt.y);
                arrowPolygon.addPoint(toPt.x+1,toPt.y-flipY*5);
                arrowPolygon.addPoint(toPt.x+4,toPt.y-flipY*5);
                arrowPolygon.addPoint(toPt.x,toPt.y);
                arrowPolygon.addPoint(toPt.x-4,toPt.y-flipY*5);
                arrowPolygon.addPoint(toPt.x-1,toPt.y-flipY*5);                    
                arrowPolygon.addPoint(fromPt.x-1,fromPt.y);
            }
        }
        return transform.createTransformedShape(arrowPolygon);
    }

}
